home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.7 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  9.6 KB  |  379 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 5.7: Level-of-Detail Example                        //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include <vector>
  9. #include "debug.h"
  10. #include "mouse.h"
  11. #include "object.h"
  12. #include "camera.h"
  13.  
  14. struct VERTEX
  15. {
  16.     VERTEX(D3DXVECTOR3 p, D3DCOLOR c){pos = p;color = c;}
  17.  
  18.     D3DXVECTOR3 pos;
  19.     D3DCOLOR color;
  20.     static const DWORD FVF;
  21. };
  22.  
  23. const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
  24.  
  25.  
  26. class APPLICATION
  27. {
  28.     public:
  29.         APPLICATION();
  30.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  31.         HRESULT Update(float deltaTime);
  32.         HRESULT Render();
  33.         HRESULT Cleanup();
  34.         HRESULT Quit();
  35.  
  36.     private:
  37.         IDirect3DDevice9* m_pDevice; 
  38.         std::vector<OBJECT> m_mechs;
  39.         std::vector<VERTEX> m_lines;
  40.         MOUSE m_mouse;
  41.         CAMERA m_camera;
  42.  
  43.         ID3DXLine *m_pLine;
  44.         D3DLIGHT9 m_light;
  45.         DWORD m_time;
  46.         int m_fps, m_lastFps;
  47.         bool m_lodOn;
  48.         HWND m_mainWindow;
  49.         ID3DXFont *m_pFont;
  50. };
  51.  
  52. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  53. {
  54.     APPLICATION app;
  55.  
  56.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  57.         return 0;
  58.  
  59.     MSG msg;
  60.     memset(&msg, 0, sizeof(MSG));
  61.     int startTime = timeGetTime(); 
  62.  
  63.     while(msg.message != WM_QUIT)
  64.     {
  65.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  66.         {
  67.             ::TranslateMessage(&msg);
  68.             ::DispatchMessage(&msg);
  69.         }
  70.         else
  71.         {    
  72.             int t = timeGetTime();
  73.             float deltaTime = (t - startTime)*0.001f;
  74.  
  75.             app.Update(deltaTime);
  76.             app.Render();
  77.  
  78.             startTime = t;
  79.         }
  80.     }
  81.  
  82.     app.Cleanup();
  83.  
  84.     return msg.wParam;
  85. }
  86.  
  87. APPLICATION::APPLICATION()
  88. {
  89.     m_pDevice = NULL; 
  90.     m_mainWindow = 0;
  91.     m_pFont = NULL;
  92.     m_pLine = NULL;
  93.     m_fps = m_lastFps = 0;
  94.     m_time = GetTickCount();
  95.     m_lodOn = true;
  96.  
  97.     srand(GetTickCount());
  98. }
  99.  
  100. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  101. {
  102.     debug.Print("Application initiated");
  103.  
  104.     //Create Window Class
  105.     WNDCLASS wc;
  106.     memset(&wc, 0, sizeof(WNDCLASS));
  107.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  108.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  109.     wc.hInstance     = hInstance;
  110.     wc.lpszClassName = "D3DWND";
  111.  
  112.     //Register Class and Create new Window
  113.     RegisterClass(&wc);
  114.     m_mainWindow = CreateWindow("D3DWND", "Example 5.7: Level-of-Detail Example", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  115.     SetCursor(NULL);
  116.     ShowWindow(m_mainWindow, SW_SHOW);
  117.     UpdateWindow(m_mainWindow);
  118.  
  119.     //Create IDirect3D9 Interface
  120.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  121.  
  122.     if(d3d9 == NULL)
  123.     {
  124.         debug.Print("Direct3DCreate9() - FAILED");
  125.         return E_FAIL;
  126.     }
  127.  
  128.     //Check that the Device supports what we need from it
  129.     D3DCAPS9 caps;
  130.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  131.  
  132.     //Hardware Vertex Processing or not?
  133.     int vp = 0;
  134.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  135.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  136.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  137.  
  138.     //Check vertex & pixelshader versions
  139.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  140.     {
  141.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  142.     }
  143.  
  144.     //Set D3DPRESENT_PARAMETERS
  145.     D3DPRESENT_PARAMETERS d3dpp;
  146.     d3dpp.BackBufferWidth            = width;
  147.     d3dpp.BackBufferHeight           = height;
  148.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  149.     d3dpp.BackBufferCount            = 1;
  150.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  151.     d3dpp.MultiSampleQuality         = 0;
  152.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  153.     d3dpp.hDeviceWindow              = m_mainWindow;
  154.     d3dpp.Windowed                   = windowed;
  155.     d3dpp.EnableAutoDepthStencil     = true; 
  156.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  157.     d3dpp.Flags                      = 0;
  158.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  159.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  160.  
  161.     //Create the IDirect3DDevice9
  162.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  163.                                  vp, &d3dpp, &m_pDevice)))
  164.     {
  165.         debug.Print("Failed to create IDirect3DDevice9");
  166.         return E_FAIL;
  167.     }
  168.  
  169.     //Release IDirect3D9 interface
  170.     d3d9->Release();
  171.  
  172.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  173.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  174.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  175.  
  176.     //Create m_light
  177.     ::ZeroMemory(&m_light, sizeof(m_light));
  178.     m_light.Type      = D3DLIGHT_DIRECTIONAL;
  179.     m_light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  180.     m_light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
  181.     m_light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  182.     m_light.Direction = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
  183.     m_pDevice->SetLight(0, &m_light);
  184.     m_pDevice->LightEnable(0, true);
  185.  
  186.     //Set sampler state
  187.     for(int i=0;i<4;i++)
  188.     {
  189.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  190.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  191.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  192.     }
  193.  
  194.     //Init camera
  195.     m_camera.Init(m_pDevice);    
  196.     m_camera.m_radius = 100.0f;
  197.  
  198.     //Load objects
  199.     LoadObjectResources(m_pDevice);
  200.  
  201.     //Create 2D Line
  202.     D3DXCreateLine(m_pDevice, &m_pLine);
  203.  
  204.     //Add m_mechs
  205.     for(int y=-12;y<12;y++)
  206.         for(int x=-12;x<12;x++)
  207.         {
  208.             if(rand()%3 == 0)
  209.             {
  210.                 float a = (rand()%(int)((D3DX_PI*2.0f)*1000)) / 1000.0f;
  211.                 m_mechs.push_back(OBJECT(MECH, D3DXVECTOR3(x * 15.0f, 0.0f, -y * 15.0f), D3DXVECTOR3(0.0f, a, 0.0f)));
  212.             }
  213.         }    
  214.  
  215.     //Create m_lines
  216.     for(int i=-12;i<=12;i++)
  217.     {
  218.         m_lines.push_back(VERTEX(D3DXVECTOR3(-180.0f, 0.0f, -i * 15.0f), 0xff000000));
  219.         m_lines.push_back(VERTEX(D3DXVECTOR3(180.0f, 0.0f, -i * 15.0f), 0xff000000));
  220.         m_lines.push_back(VERTEX(D3DXVECTOR3(i * 15.0f, 0.0f, -180.0f), 0xff000000));
  221.         m_lines.push_back(VERTEX(D3DXVECTOR3(i * 15.0f, 0.0f, 180.0f), 0xff000000));
  222.     }
  223.  
  224.  
  225.     //Init mouse
  226.     m_mouse.InitMouse(m_pDevice, m_mainWindow);
  227.  
  228.     return S_OK;
  229. }
  230.  
  231. HRESULT APPLICATION::Update(float deltaTime)
  232. {
  233.     //Control camera
  234.     D3DXMATRIX  matWorld;
  235.     D3DXMatrixIdentity(&matWorld);
  236.     m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
  237.  
  238.     //Update mouse
  239.     m_mouse.Update();
  240.  
  241.     //Update camera
  242.     m_camera.Update(m_mouse, deltaTime);
  243.  
  244.     if(KEYDOWN(VK_SPACE))
  245.     {
  246.         Sleep(200);
  247.         m_lodOn = !m_lodOn;
  248.     }
  249.     else if(KEYDOWN(VK_ESCAPE))
  250.         Quit();
  251.  
  252.     return S_OK;
  253. }    
  254.  
  255.  
  256. HRESULT APPLICATION::Render()
  257. {
  258.     // Clear the viewport
  259.     D3DVIEWPORT9 v, v2;
  260.     v.X = 0;
  261.     v.Y = 0;
  262.     v.Width = 800;
  263.     v.Height = 600;
  264.     v.MaxZ = 1.0f;
  265.     v.MinZ = 0.0f;
  266.     v2 = v;
  267.     m_pDevice->SetViewport(&v);
  268.     m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  269.  
  270.     //FPS Calculation
  271.     m_fps++;
  272.     if(GetTickCount() - m_time > 1000)
  273.     {
  274.         m_lastFps = m_fps;
  275.         m_fps = 0;
  276.         m_time = GetTickCount();
  277.     }
  278.  
  279.     // Begin the scene 
  280.     if(SUCCEEDED(m_pDevice->BeginScene()))
  281.     {
  282.         //Draw m_lines
  283.         m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  284.         m_pDevice->SetFVF(VERTEX::FVF);
  285.  
  286.         for(int i=0;i<m_lines.size();i+=2)
  287.             m_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 1, &m_lines[i], sizeof(VERTEX));
  288.  
  289.         m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
  290.  
  291.         //Draw Mechs
  292.         long noFaces = 0;
  293.         int noObjects = 0;
  294.  
  295.         for(int i=0;i<m_mechs.size();i++)
  296.         {
  297.             if(m_lodOn)
  298.                 m_mechs[i].Render(&m_camera, noFaces, noObjects);
  299.             else m_mechs[i].Render(NULL, noFaces, noObjects);
  300.         }
  301.  
  302.         //Top menu
  303.         v.X = 0;
  304.         v.Y = 0;
  305.         v.Width = 800;
  306.         v.Height = 70;
  307.         m_pDevice->SetViewport(&v);
  308.         m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  309.  
  310.         //Number of Mechs
  311.         RECT r[] = {{500, 10, 0, 0}, {500, 30, 0, 0}, {500, 50, 0, 0},
  312.                     {10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}};
  313.  
  314.         char number[50];
  315.         std::string text = "Num Mechs in screen: ";
  316.         text += _itoa(noObjects, number, 10);
  317.         text += " / ";
  318.         text += _itoa(m_mechs.size(), number, 10);
  319.         m_pFont->DrawText(NULL, text.c_str(), -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  320.  
  321.         //Number of Polygons
  322.         text = "Num Total Polygons: ";
  323.         text += _itoa(noFaces, number, 10);
  324.         m_pFont->DrawText(NULL, text.c_str(), -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  325.  
  326.         //FPS
  327.         text = "FPS: ";
  328.         text += _itoa(m_lastFps, number, 10);
  329.         m_pFont->DrawText(NULL, text.c_str(), -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  330.  
  331.         //Controls
  332.         m_pFont->DrawText(NULL, "Mouse Wheel: Change Camera Radius", -1, &r[3], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  333.         m_pFont->DrawText(NULL, "Arrows: Change Camera Angle", -1, &r[4], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  334.  
  335.         if(m_lodOn)
  336.             m_pFont->DrawText(NULL, "Space: LOD & Culling = On", -1, &r[5], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  337.         else m_pFont->DrawText(NULL, "Space: LOD & Culling = Off", -1, &r[5], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  338.         
  339.         //Restore viewport
  340.         m_pDevice->SetViewport(&v2);
  341.  
  342.         D3DXVECTOR2 l[] = {D3DXVECTOR2(0.0f, 70.0f), D3DXVECTOR2(800.0f, 70.0f)};
  343.         m_pLine->Begin();
  344.         m_pLine->SetWidth(4.0f);
  345.         m_pLine->Draw(l, 2, 0xff000000);
  346.         m_pLine->End();
  347.         
  348.         //Draw mouse
  349.         m_mouse.Paint();
  350.  
  351.         // End the scene.
  352.         m_pDevice->EndScene();
  353.         m_pDevice->Present(0, 0, 0, 0);
  354.     }
  355.  
  356.     return S_OK;
  357. }
  358.  
  359. HRESULT APPLICATION::Cleanup()
  360. {
  361.     try
  362.     {
  363.         m_pFont->Release();
  364.         m_pLine->Release();
  365.         m_pDevice->Release();
  366.  
  367.         debug.Print("Application terminated");
  368.     }
  369.     catch(...){}
  370.  
  371.     return S_OK;
  372. }
  373.  
  374. HRESULT APPLICATION::Quit()
  375. {
  376.     ::DestroyWindow(m_mainWindow);
  377.     ::PostQuitMessage(0);
  378.     return S_OK;
  379. }